import uuid
from typing import Optional, Union, Dict, Any

from fastapi import Depends, Request
from fastapi_users import BaseUserManager, FastAPIUsers, UUIDIDMixin, models
from fastapi_users.authentication import (
    AuthenticationBackend,
    BearerTransport,
    JWTStrategy,
)
from fastapi_users.db import SQLAlchemyUserDatabase
from fastapi_users.models import UP
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from datetime import datetime
from jose import jwt

from app.models.db import User, get_user_db, Role, UserRole
from config import JWT_SECRET, JWT_EXPIRE_SECONDS

SECRET = JWT_SECRET
ALGORITHM = "HS256"

class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
    reset_password_token_secret = SECRET
    verification_token_secret = SECRET

    async def on_after_register(self, user: User, request: Optional[Request] = None):
        # 用户注册后自动设置为已验证状态，无需邮箱验证
        await self.user_db.update(user, {"is_verified": True})
        
        # 获取数据库会话
        session = self.user_db.session
        
        try:
            # 为新用户分配默认角色（普通用户或一般用户）
            default_role_query = select(Role).where(
                Role.name.in_(["普通用户", "一般用户"])
            )
            default_role_result = await session.execute(default_role_query)
            default_role = default_role_result.scalar_one_or_none()
            
            if default_role:
                # 创建用户角色关联
                user_role = UserRole(
                    user_id=str(user.id),
                    role_id=default_role.id,
                    created_at=datetime.now()
                )
                session.add(user_role)
                await session.commit()
        except Exception as e:
            # 记录错误但不中断注册流程
            await session.rollback()

    async def on_after_forgot_password(
        self, user: User, token: str, request: Optional[Request] = None
    ):
        print(f"User {user.id} has forgot their password. Reset token: {token}")

    # 邮箱验证相关方法保留但不使用
    async def on_after_request_verify(
        self, user: User, token: str, request: Optional[Request] = None
    ):
        # 由于禁用了验证，此方法不会被调用
        pass

    @staticmethod
    async def decode_token_and_get_user(token: str) -> Optional[str]:
        """解码JWT token并获取用户"""
        try:
            # 1. 解码 Token - 禁用audience验证
            payload = jwt.decode(
                token, 
                SECRET, 
                algorithms=[ALGORITHM],
                options={
                    "verify_aud": False,  # 禁用audience验证
                    "verify_iss": False,  # 禁用issuer验证
                }
            )
            user_id = payload.get("sub")
            
            if not user_id:
                print(f"Token payload中没有找到sub字段: {payload}")
                return None
            return user_id
        except Exception as e:
            print(f"Token解码错误: {e}")
            return ""

    async def authenticate(self, credentials) -> Optional[UP]:
        """自定义认证方法，支持用户名或邮箱登录"""
        # 处理OAuth2PasswordRequestForm
        if hasattr(credentials, "username") and hasattr(credentials, "password"):
            username = credentials.username
            password = credentials.password
        # 处理字典类型的凭据
        elif isinstance(credentials, dict) and "username" in credentials and "password" in credentials:
            username = credentials["username"]
            password = credentials["password"]
        else:
            return None
            
        # 尝试通过用户名查找用户
        user = await self.user_db.get_by_username(username)
        
        # 如果用户名未找到，尝试通过邮箱查找（向后兼容）
        if user is None and "@" in username:
            try:
                user = await self.user_db.get_by_email(username)
            except Exception:
                pass
                
        if user is None:
            # 用户不存在
            return None
            
        verified, updated_password_hash = self.password_helper.verify_and_update(
            password, user.hashed_password
        )
        if not verified:
            # 密码不正确
            return None
            
        # 如果密码哈希需要更新
        if updated_password_hash is not None:
            await self.user_db.update(user, {"hashed_password": updated_password_hash})
            
        return user

    async def get_user_profile(self, user_identifier: Union[str, uuid.UUID]) -> Optional[Dict[str, Any]]:
        """
        获取用户完整档案信息，包括基本信息、部门、角色等
        
        Args:
            user_identifier: 用户ID(UUID)或用户名(str)
            
        Returns:
            用户档案信息字典，包含所有相关信息供AI使用
        """
        try:
            session = self.user_db.session
            
            # 根据标识符类型查询用户
            if isinstance(user_identifier, str):
                try:
                    # 尝试解析为UUID
                    user_uuid = uuid.UUID(user_identifier)
                    # 通过ID查询
                    user_query = select(User).where(User.id == user_uuid)
                except ValueError:
                    # 不是UUID，当作用户名处理
                    user_query = select(User).where(User.username == user_identifier)
            else:
                # 直接使用UUID查询
                user_query = select(User).where(User.id == user_identifier)
            
            # 执行查询
            user_result = await session.execute(user_query)
            user = user_result.scalar_one_or_none()
            
            if not user:
                return None
            
            # 查询用户角色信息
            roles_query = (
                select(Role)
                .select_from(Role)
                .join(UserRole, Role.id == UserRole.role_id)
                .where(UserRole.user_id == str(user.id))
            )
            roles_result = await session.execute(roles_query)
            user_roles = roles_result.scalars().all()
            
            # 构建用户档案信息
            user_profile = {
                # 基本身份信息
                "user_id": str(user.id),
                "username": user.username,
                "email": user.email,
                "phone": user.phone,
                "nickname": user.nickname,
                
                # 个人信息
                "gender": user.gender,
                "birthday": user.birthday.isoformat() if user.birthday else None,
                "avatar": user.avatar,
                
                # 组织信息
                "department": user.department,
                "position": user.position,
                
                # 角色信息
                "roles": [
                    {
                        "id": role.id,
                        "name": role.name,
                        "description": role.description,
                        "is_system": role.is_system
                    } for role in user_roles
                ],
                "role_names": [role.name for role in user_roles],
                "primary_role": user_roles[0].name if user_roles else None,
                
                # 状态信息
                "is_active": user.is_active,
                "is_superuser": user.is_superuser,

                
                # 权限相关（用于AI判断数据访问范围）
                
                # 时间信息
                "created_at": user.created_at.isoformat() if user.created_at else None,
                "updated_at": user.updated_at.isoformat() if user.updated_at else None,
            }
            
            return user_profile
            
        except Exception as e:
            print(f"获取用户档案失败: {e}")
            return None
    
async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
    yield UserManager(user_db)



bearer_transport = BearerTransport(tokenUrl="/dk/auth/jwt/login")


def get_jwt_strategy() -> JWTStrategy[models.UP, models.ID]:
    return JWTStrategy(secret=SECRET, lifetime_seconds=JWT_EXPIRE_SECONDS)


auth_backend = AuthenticationBackend(
    name="jwt",
    transport=bearer_transport,
    get_strategy=get_jwt_strategy,
)

fastapi_users = FastAPIUsers[User, uuid.UUID](
    get_user_manager, 
    [auth_backend],
)

# 获取当前活跃用户依赖项，不要求验证
current_active_user = fastapi_users.current_user(active=True, verified=False)

# 将全局需要验证标志设置为False
fastapi_users.requires_verification = False


# 便捷的用户档案获取函数
async def get_user_profile_by_identifier(user_identifier: Union[str, uuid.UUID]) -> Optional[Dict[str, Any]]:
    """
    便捷函数：获取用户完整档案信息
    
    Args:
        user_identifier: 用户ID(UUID)或用户名(str)
        
    Returns:
        用户档案信息字典，供AI使用
        
    Example:
        # 通过用户ID获取
        profile = await get_user_profile_by_identifier("123e4567-e89b-12d3-a456-426614174000")
        
        # 通过用户名获取
        profile = await get_user_profile_by_identifier("admin")
        
        # 获取到的profile包含：
        # {
        #     "user_id": "123e4567-e89b-12d3-a456-426614174000",
        #     "username": "admin",
        #     "department": "技术部",
        #     "position": "开发工程师",
        #     "roles": [{"name": "管理员", ...}],
        #     "access_scope": "system",
        #     "data_filter_conditions": {...},
        #     ...
        # }
    """
    from app.models.db import get_user_db, get_async_session
    
    # 获取数据库会话
    async for session in get_async_session():
        try:
            # 获取用户数据库实例
            async for user_db in get_user_db(session):
                # 创建UserManager实例
                user_manager = UserManager(user_db)
                
                # 获取用户档案
                profile = await user_manager.get_user_profile(user_identifier)
                return profile
        except Exception as e:
            print(f"获取用户档案时发生错误: {e}")
            return None
        finally:
            await session.close()
    
    return None
